/**
 * 成员路由
 * 处理成员的 CRUD 操作、批量导入、微信绑定等功能
 */

import { FastifyPluginAsync } from 'fastify'
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
import { Type } from '@sinclair/typebox'
import {
    CreateMemberSchema,
    CreateMemberResponseSchema,
    UpdateMemberSchema,
    UpdateMemberResponseSchema,
    GetMemberResponseSchema,
    DeleteMemberResponseSchema,
    MemberListQuerySchema,
    MemberListResponseSchema,
    BindWechatSchema,
    BindWechatResponseSchema,
    BatchCreateMembersSchema,
    BatchCreateMembersResponseSchema,
    UpdateMemberGroupsResponseSchema
} from '../validators/member.schema'
import {
    createMember,
    createMemberFromList,
    readMember,
    readMemberList,
    updateMember,
    deleteMember,
    associateMemberWithWxid,
    updateMemberGroup
} from '../repos/member.repo'

const memberRoutes: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
    const server = fastify.withTypeProvider<TypeBoxTypeProvider>()

    /**
     * 创建成员
     * POST /api/members
     */
    server.post(
        '/api/members',
        {
            schema: {
                description: '创建新成员',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                body: CreateMemberSchema,
                response: {
                    201: CreateMemberResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const body = request.body

            const result = await createMember(body.organizationId!, body.identifier!, body.realName!)

            if (!result.status) {
                throw new Error(result.message || '创建成员失败')
            }

            // 转换 Date 为 ISO string
            const data = result.data as any
            const transformedData = {
                ...data,
                createdAt: data.createdAt.toISOString(),
                updatedAt: data.updatedAt.toISOString()
            }

            return reply.status(201).send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 获取成员信息
     * GET /api/members/:type/:value
     */
    server.get(
        '/api/members/:type/:value',
        {
            schema: {
                description: '根据 ID、学号或微信 OpenID 获取成员信息',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        type: {
                            type: 'string',
                            enum: ['id', 'identifier', 'wxOpenId'],
                            description: '查询类型'
                        },
                        value: { type: 'string', description: '查询值' }
                    },
                    required: ['type', 'value']
                },
                response: {
                    200: GetMemberResponseSchema
                }
            },
            preHandler: [server.authenticate]
        },
        async (request, reply) => {
            const { type, value } = request.params as { type: 'id' | 'identifier' | 'wxOpenId'; value: string }

            const result = await readMember(type, value)

            if (!result.status) {
                throw new Error(result.message || '获取成员信息失败')
            }

            // 转换 Date 为 ISO string
            const data = (result.data as any[]).map((item: any) => ({
                ...item,
                createdAt: item.createdAt.toISOString(),
                updatedAt: item.updatedAt.toISOString()
            }))

            return reply.send({
                success: true,
                data
            })
        }
    )

    /**
     * 更新成员信息
     * PUT /api/members/:id
     */
    server.put(
        '/api/members/:id',
        {
            schema: {
                description: '更新成员信息',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        id: { type: 'string', format: 'uuid' }
                    },
                    required: ['id']
                },
                body: UpdateMemberSchema,
                response: {
                    200: UpdateMemberResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { id } = request.params as { id: string }
            const body = request.body

            // 如果两个字段都没有，抛出错误
            if (!body.realName && !body.nickName) {
                throw new Error('至少需要提供一个字段进行更新')
            }

            const result = await updateMember(id, body.realName || '', body.nickName || '')

            if (!result.status) {
                throw new Error(result.message || '更新成员失败')
            }

            // 转换 Date 为 ISO string
            const data = result.data as any
            const transformedData = {
                ...data,
                createdAt: data.createdAt.toISOString(),
                updatedAt: data.updatedAt.toISOString()
            }

            return reply.send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 删除成员
     * DELETE /api/members/:id
     */
    server.delete(
        '/api/members/:id',
        {
            schema: {
                description: '删除成员（软删除）',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        id: { type: 'string', format: 'uuid' }
                    },
                    required: ['id']
                },
                response: {
                    200: DeleteMemberResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { id } = request.params as { id: string }

            const result = await deleteMember(id)

            if (!result.status) {
                throw new Error(result.message || '删除成员失败')
            }

            return reply.send({
                success: true,
                data: {
                    deleted: true
                }
            })
        }
    )

    /**
     * 获取成员列表
     * GET /api/members
     */
    server.get(
        '/api/members',
        {
            schema: {
                description: '获取成员列表（支持分页和筛选）',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                querystring: MemberListQuerySchema,
                response: {
                    200: MemberListResponseSchema
                }
            },
            preHandler: [server.authenticate]
        },
        async (request, reply) => {
            const query = request.query as any

            const result = await readMemberList(
                query.organizationId,
                query.offset || 0,
                query.limit || 20,
                query.displayDelete || false
            )

            if (!result.status) {
                throw new Error(result.message || '获取成员列表失败')
            }

            const resultData = result.data as any

            // 转换 Date 为 ISO string
            const transformedData = {
                data: resultData.result.map((item: any) => ({
                    ...item,
                    createdAt: item.createdAt.toISOString(),
                    updatedAt: item.updatedAt.toISOString()
                })),
                total: resultData.total,
                offset: query.offset || 0,
                limit: query.limit || 20,
                hasMore: resultData.total > (query.offset || 0) + (query.limit || 20)
            }

            return reply.send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 绑定微信
     * POST /api/members/bind-wechat
     */
    server.post(
        '/api/members/bind-wechat',
        {
            schema: {
                description: '绑定成员与微信账号',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                body: BindWechatSchema,
                response: {
                    200: BindWechatResponseSchema
                }
            },
            preHandler: [server.authenticate]
        },
        async (request, reply) => {
            const body = request.body

            const result = await associateMemberWithWxid(body.memberId!, body.wxOpenId!, body.nickName || '')

            if (!result.status) {
                throw new Error(result.message || '绑定微信失败')
            }

            // 转换 Date 为 ISO string
            const data = result.data as any
            const transformedData = {
                ...data,
                createdAt: data.createdAt.toISOString(),
                updatedAt: data.updatedAt.toISOString()
            }

            return reply.send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 批量创建成员
     * POST /api/members/batch
     */
    server.post(
        '/api/members/batch',
        {
            schema: {
                description: '批量创建成员',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                body: BatchCreateMembersSchema,
                response: {
                    201: BatchCreateMembersResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const body = request.body

            // 转换数据格式
            const members = body.members!.map(m => ({
                organizationId: body.organizationId!,
                identifier: m.identifier!,
                realName: m.realName!,
                nickName: m.nickName,
                wxOpenId: m.wxOpenId
            }))

            const result = await createMemberFromList(members)

            if (!result.status) {
                throw new Error(result.message || '批量创建成员失败')
            }

            const data = result.data as any

            return reply.status(201).send({
                success: true,
                data: {
                    count: data.count,
                    skipped: body.members!.length - data.count
                }
            })
        }
    )

    /**
     * 更新成员分组
     * PUT /api/members/:id/groups
     */
    server.put(
        '/api/members/:id/groups',
        {
            schema: {
                description: '更新成员所属的群组',
                tags: ['成员'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        id: { type: 'string', format: 'uuid' }
                    },
                    required: ['id']
                },
                body: Type.Object({
                    organizationId: Type.String({ format: 'uuid' }),
                    groupIds: Type.Array(Type.String({ format: 'uuid' }))
                }),
                response: {
                    200: UpdateMemberGroupsResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { id } = request.params as { id: string }
            const body = request.body as any

            const result = await updateMemberGroup(body.organizationId, id, body.groupIds)

            if (!result.status) {
                throw new Error(result.message || '更新成员分组失败')
            }

            const data = result.data as any

            return reply.send({
                success: true,
                data: {
                    added: data.adds,
                    removed: data.deletes,
                    failed: data.fails
                }
            })
        }
    )
}

export default memberRoutes

// fastify-autoload will use this exported 'prefix' when mounting the plugin
export const prefix = '/api/members'
